/**
 * copyright https://blog.csdn.net/Z_Stand/article/details/108395906
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

char kStr[] = "Ptrace is testing!";

void CheckArguments(long ret, char* str) {
    if (-1 == ret) {
        printf("excute %s failed with %ld\n", str, ret);
        return;
    }
    printf("excute %s success\n", str);
}

int main(int argc, char** argv) {
    pid_t pid = fork();

    union {
        char      c_data[8];
        u_int64_t data;
    } u = {"change T"};

    if (0 == pid) {
        sleep(2);  // 子进程休眠2s
        printf("child data is %s\n", kStr);
    } else if (pid > 0) {
        // 父进程
        // 1. 附加到子进程
        CheckArguments(ptrace(PTRACE_ATTACH, pid, NULL, NULL), "ptrace_attach");
        // 2. 修改子进程内存中kStr的内容
        CheckArguments(ptrace(PTRACE_POKEDATA, pid, (void*)kStr, u.data), "ptrace_pokedata");
        // 3. 子进程继续运行
        CheckArguments(ptrace(PTRACE_CONT, pid, NULL, NULL), "ptrace_continue");

        printf("parent data is %s\n", kStr);
        // 4. 等待子进程结束
        wait(NULL);
    } else {
        printf("fork failed\n");
    }
    return 0;
}
